<body>
	<!-- <p class="foo bar"></p> -->
</body>

<script type="module">
	import normalizeClass from './normalizeClass.js'
	const el = document.querySelector('button')
	function createRenderer(optios) {
		const {createElement, setElementText, insert} = optios
		//特殊处理
		function shouldSetAsProps(el, key, value) {
			if (key === 'form' && el.tagName === 'INPUT') return false
			return key in el
		}
		// patchProps：用于更新 DOM 元素的属性。根据属性的类型（DOM 属性或 HTML 属性）选择合适的设置方式。
		function patchProps(el, key, value) {
			if (key === 'class') {
				el.className = normalizeClass(value) // 调用封装的 normalizeClass 函
			} else if (shouldSetAsProps(el, key, value)) {
				const type = typeof el[key] //  获取该 DOM 属性值 的类型
				if (type === 'boolean' && value === '') {
					el[key] = true // 如果是dom使用标准是布尔值，并且当前value是空，将值矫正为true
				} else {
					el[key] = value
				}
			} else {
				el.setAttribute(key, value)
			}
		}

		// 挂载
		function mountElement(vnode, container) {
			// 2、让 vnode.el 存一份 真实 DOM 元素 对的指针 ，用于回收元素
			const el = (vnode.el = createElement(vnode.type))

			if (typeof vnode.children === 'string') {
				setElementText(el, vnode.children) //元素是字符串，直接设置文本
			} else if (Array.isArray(vnode.children)) {
				vnode.children.forEach((child) => {
					patch(null, child, el) // 子节点是数组，遍历child调用patch挂载他们
				})
			}

			if (vnode.props) {
				for (const key in vnode.props) {
					patchProps(el, key, vnode.props[key]) // 区分更新
				}
			}
			insert(el, container)
		}

		// patch
		function patch(n1, n2, container) {
			if (!n1) {
				mountElement(n2, container)
			} else {
				console.log('n1存在, 意味需要打补丁，暂时没做到')
			}
		}

		// 分支
		function render(vnode, container) {
			// console.log(vnode, container) // vnode虚拟dom，container挂载点(暂是document.body）
			if (vnode) {
				patch(container._vnode, vnode, container)
			} else {
				//3、vnode是null，进入清空 元素
				if (container._vnode) {
					const el = container._vnode.el // 使用前面存旧的元素(代码33行)
					const parent = el.parentNode //获取父元素去移除元素
					if (parent) parent.removeChild(el)
				}
			}
			container._vnode = vnode // container.vnode代表旧的vnode
		}
		return {render}
	}

	// 渲染器
	const renderer = createRenderer({
		createElement(tag) {
			return document.createElement(tag)
		},
		setElementText(el, text) {
			el.textContent = text
		},
		insert(el, parent, anchor = null) {
			parent.insertBefore(el, anchor)
		}
	})
	const vnode = {
		type: 'p',
		props: {class: {foo: true, bar: false}},
		children: '我会被removeChild'
	}
	// 这是渲染，传递虚拟dom，挂载点
	renderer.render(vnode, document.body)
	setTimeout(() => {
		// 1、传递null，去实现卸载
		renderer.render(null, document.body)
	}, 2000)
</script>
